package vip.wangwenhao.autoconfigure.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import vip.wangwenhao.autoconfigure.constants.Oauth2Constants;
import vip.wangwenhao.common.constants.CommonConstants;
import vip.wangwenhao.common.constants.SymbolConstants;
import vip.wangwenhao.common.exception.CommonException;

import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.List;


/**
 * @author wwh
 * @date 2020年01月15日 15:44
 */

public class Oauth2Utils {

    /**
     * 判断请求头中是否包含client信息，不包含返回null  Base64编码
     */
    public static String[] isHasClientDetails(HttpServletRequest request) {

        String[] params = null;

        String header = request.getHeader(HttpHeaders.AUTHORIZATION);

        if (header != null) {


            if (header.startsWith(Oauth2Constants.CLIENT_INFO_PREFIX)) {

                String tmp = header.substring(6);
                String defaultClientDetails = new String(Base64.getDecoder().decode(tmp));

                String[] clientArrays = defaultClientDetails.split(Oauth2Constants.CLIENT_INFO_DELIMITER);

                if (clientArrays.length != Oauth2Constants.CLIENT_INFO_LENGTH) {
                    throw new CommonException("invalid client info");
                } else {
                    params = clientArrays;
                }

            } else {
                throw new CommonException("Missing client info prefix");
            }
        }
        String id = request.getParameter("client_id");
        String secret = request.getParameter("client_secret");

        if (header == null && id != null) {
            params = new String[]{id, secret};
        }
        if (null == params) {
            throw new CommonException("Missing client info");
        }
        return params;
    }

    public static String getToken(HttpServletRequest request) {
        String token;
        String header = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StringUtils.isNotBlank(header) && header.startsWith(Oauth2Constants.BEARER_AUTHENTICATION)) {
            String[] split = header.split(SymbolConstants.BLANK);
            if (CommonConstants.TWO.equals(split.length)) {
                token = split[1];
            } else {
                token = header;
            }
        } else {
            token = request.getParameter(Oauth2Constants.ACCESS_TOKEN_QUERY_NAME);
        }
        return token;
    }

    public static UsernamePasswordAuthenticationToken convertToken(JSONObject data, HttpServletRequest request) {
        if (null == data || data.isEmpty()){
            return null;
        }
        Object principal = data.get("principal");
        JSONObject principalJSONObject = JSONObject.parseObject(JSONObject.toJSONString(principal));
        String username = principalJSONObject.getString("username");
        String password = principalJSONObject.getString("password");
        Boolean accountNonExpired = principalJSONObject.getBoolean("accountNonExpired");
        Boolean accountNonLocked = principalJSONObject.getBoolean("accountNonLocked");
        Boolean credentialsNonExpired = principalJSONObject.getBoolean("credentialsNonExpired");
        Boolean enabled = principalJSONObject.getBoolean("enabled");
        List<SimpleGrantedAuthority> simpleGrantedAuthorityList = Lists.newArrayList();
        JSONArray authorities = principalJSONObject.getJSONArray("authorities");
        if (null != authorities && !authorities.isEmpty()) {
            authorities.forEach(jsonObject -> {
                JSONObject authorityJSONObject = (JSONObject) jsonObject;
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(authorityJSONObject.getString("authority"));
                simpleGrantedAuthorityList.add(authority);
            });
        }
        User user = new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, simpleGrantedAuthorityList);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null);
        usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        return usernamePasswordAuthenticationToken;
    }
}